
package JET.SwingUtils;

import JET.Centers.ControlCenter;
import JET.Frames.DataModels.DataModelsFactory;
import JET.Scene;
import JET.SceneHelper;
import JET.physics.engine.JETContext;
import JET.physics.Mass;
import JET.physics.RSpring;
import JET.physics.Spring;
import JET.physics.Wall;
import JET.physics.bodies.SpringBody;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.swing.JTree;
import javax.swing.tree.TreePath;

/**
 *
 * @author 057Ry
 */

public class TreeUtil {

    ////////////////////////////////////////////////////////////////////////////
    //                        PREVENTING TREE COLLAPSING                      //
    //              @author santhosh kumar T - santhosh@in.fiorano.com        //
    ////////////////////////////////////////////////////////////////////////////

    public static boolean isDescendant(TreePath path1, TreePath path2){
        int count1 = path1.getPathCount();
        int count2 = path2.getPathCount();
        if(count1<=count2)
            return false;
        while(count1!=count2){
            path1 = path1.getParentPath();
            count1--;
        }
        return path1.equals(path2);
    }

    public static String getExpansionState(JTree tree, int row){
        TreePath rowPath = tree.getPathForRow(row);
        StringBuffer buf = new StringBuffer();
        int rowCount = tree.getRowCount();
        for(int i=row; i<rowCount; i++){
            TreePath path = tree.getPathForRow(i);
            if(i==row || isDescendant(path, rowPath)){
                if(tree.isExpanded(path))
                    buf.append(","+String.valueOf(i-row));
            }else
                break;
        }
        return buf.toString();
    }

    public static void restoreExpanstionState(JTree tree, int row, String expansionState){
        StringTokenizer stok = new StringTokenizer(expansionState, ",");
        while(stok.hasMoreTokens()){
            int token = row + Integer.parseInt(stok.nextToken());
            tree.expandRow(token);
        }
    }
    
    ////////////////////////////////////////////////////////////////////////////
    
    /**
     * Looks for and returns last appearance of specified Class instance.
     * If no such object is present null is returned.
     * 
     * @param c Class of object that we are looking for
     * @param path Tree Path that we are looking in for specified Class object
     * @return Last appearance of specified calss object in tree path
     */
    public static Object getLastInstanceOfClassFromPath(TreePath path, Class c) {
        Object[] objs = path.getPath();
        
        for (int i=objs.length-1; i>=0; i--)
            if ( c.isInstance(objs[i]) )
                return objs[i];
        
        return null;
    }

    /**
     * Looks for and returns selected instances of objects of specified class.
     *
     * @param tree Tree in which we look for specified selected objects
     * @param c Specifies the object-to-look for class
     * @return ArrayList filled with interesting objects, if no objects were found empty list is returned.
     */
    public static ArrayList<Object> getSelectedInstancesOfClass(JTree tree, Class c) {
        ArrayList<Object> list = new ArrayList<Object>();
        
        TreePath[] paths = tree.getSelectionPaths();
        if (paths!=null)
            for (TreePath p : paths)
                if ( c.isInstance(p.getLastPathComponent()) )
                    list.add(p.getLastPathComponent());

        return list;
    }

    ////////////////////////////////////////////////////////////////////////////
    //                  S C E N E   T R E E   U T I L S                       //
    ////////////////////////////////////////////////////////////////////////////
    
    public static TreePath getObjectPath(Object o, Scene scene) {
            ControlCenter CC = ControlCenter.getInstance();
            JETContext e = scene.getJETContext();

            if (o instanceof Mass) {
                SpringBody sb = SceneHelper.getSpringBodyThatOwnMass(scene, (Mass) o);

                if (sb!=null)
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.springBodiesTreeNode,
                                         sb,
                                         sb.massesTreeNode,
                                         o
                                        });
            }
            else if (o instanceof Wall) {
                SpringBody sb = SceneHelper.getSpringBodyThatOwnWall(scene, (Wall) o);

                if (sb!=null)
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.springBodiesTreeNode,
                                         sb,
                                         sb.wallsTreeNode,
                                         o
                                        });
            }
            else if (o instanceof Spring) {
                SpringBody sb = SceneHelper.getSpringBodyThatOwnSpring(scene, (Spring) o);

                if (sb != null)
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.springBodiesTreeNode,
                                         sb,
                                         sb.springsTreeNode,
                                         o
                                        });
                else
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.springsTreeNode,
                                         o
                                        });
            }
            else if (o instanceof RSpring) {
                SpringBody sb = SceneHelper.getSpringBodyThatOwnRSpring(scene, (RSpring) o);

                if (sb != null)
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.springBodiesTreeNode,
                                         sb,
                                         sb.rSpringsTreeNode,
                                         o
                                        });
                else
                    return new TreePath(new Object[] {DataModelsFactory.getSceneTreeModel().sceneRootNode,
                                         e.rSpringsTreeNode,
                                         o
                                        });
            }

            return null;
        }
}
